import axios from "axios";
import { getData, setData, getCoinChats } from "./db";
import dayjs from "dayjs";
import { pick } from "lodash";
import utils from "./utils";
let { sendable, getUniCode, sendMessage, setExpires } = utils
interface Coin {
  symbol: string;
  time: number;
  price: number;
}

interface HistoricalData {
  [key: string]: {
    [timestamp: string]: number;
  };
}

const PRICE_THRESHOLDS = {
  ONE_MIN: 0.015,
  FIVE_MIN: 0.025,
  ONE_HOUR: 0.05,
};

const getTimeFormats = () => {
  const now = dayjs();
  const minuteFormats = Array.from({ length: 11 }, (_, i) =>
    now.add(-i, "minutes").format("YYYY-MM-DD HH:mm"),
  );

  return [
    ...minuteFormats,
    now.format("YYYY-MM-DD HH"),
    now.format("YYYY-MM-DD"),
    now.add(-1, "hours").format("YYYY-MM-DD HH"),
    now.add(-1, "days").format("YYYY-MM-DD"),
  ];
};

const updateHistoricalData = async (
  coin: Coin,
  historicalData: HistoricalData,
) => {
  const timeFormats = {
    minute: dayjs(coin.time).format("YYYY-MM-DD HH:mm"),
    hour: dayjs(coin.time).format("YYYY-MM-DD HH"),
    day: dayjs(coin.time).format("YYYY-MM-DD"),
  };

  const his = historicalData[coin.symbol] || {};
  Object.entries(timeFormats).forEach(([_, format]) => {
    his[format] = coin.price;
  });

  return pick(his, getTimeFormats());
};

const notifyPriceChange = async (
  coin: Coin,
  previousPrice: number,
  timePeriod: string,
  threshold: number,
  timeType?: string,
  chats?: string[],
) => {
  if (!sendable(getUniCode(coin.symbol), timeType)) return;

  const priceChange = Math.abs((previousPrice - coin.price) / previousPrice);
  if (priceChange <= threshold) return;

  const percentage =
    Math.round(((coin.price - previousPrice) / previousPrice) * 10000) / 100;
  const text = `${getUniCode(coin.symbol)} ${timePeriod}${
    percentage > 0 ? "上涨" : "下跌"
  }${percentage}%, 现价${coin.price} (binance) `;

  console.log(text);
  setExpires(getUniCode(coin.symbol), timeType);

  if (!chats) {
    chats = await getCoinChats(coin.symbol);
  }

  for (const chat of chats) {
    await sendMessage(chat, text);
  }
};


export async function priceJob() {

  const { data } = await axios.get("https://maneki.cc/api/coins");
  console.log('price job ' + dayjs().format('MM-DD HH:mm:ss'))
  const historicalData = await getData();
  for (const coin of data) {
    historicalData.his[coin.symbol] = await updateHistoricalData(
      coin,
      historicalData.his || {},
    );

    await setData(historicalData);
    const chats = await getCoinChats(coin.symbol);
    await checkRule(coin, historicalData.his[coin.symbol], chats);
  }
}

const checkRule = async (
  coin: Coin,
  his: { [key: string]: number },
  chats: string[],
) => {
  const timestamps = {
    lastMin: dayjs(coin.time).add(-1, "minutes").format("YYYY-MM-DD HH:mm"),
    lastFiveMin: dayjs(coin.time).add(-5, "minutes").format("YYYY-MM-DD HH:mm"),
    lastHour: dayjs(coin.time).add(-1, "hours").format("YYYY-MM-DD HH"),
  };

  if (his[timestamps.lastMin]) {
    await notifyPriceChange(
      coin,
      his[timestamps.lastMin],
      "1分钟",
      PRICE_THRESHOLDS.ONE_MIN,
      undefined,
      chats,
    );
  }

  if (his[timestamps.lastFiveMin]) {
    await notifyPriceChange(
      coin,
      his[timestamps.lastFiveMin],
      "5分钟",
      PRICE_THRESHOLDS.FIVE_MIN,
      undefined,
      chats,
    );
  }

  if (his[timestamps.lastHour]) {
    await notifyPriceChange(
      coin,
      his[timestamps.lastHour],
      "1小时内",
      PRICE_THRESHOLDS.ONE_HOUR,
      "hour",
      chats,
    );
  }
};
